home *** CD-ROM | disk | FTP | other *** search
/ Languguage OS 2 / Languguage OS II Version 10-94 (Knowledge Media)(1994).ISO / gnu / nihcl-30.lha / nihcl-3.0 / lib / Class.c < prev    next >
C/C++ Source or Header  |  1990-05-19  |  9KB  |  357 lines

  1. /* Class.c -- implementation of class descriptor objects
  2.  
  3.     THIS SOFTWARE FITS THE DESCRIPTION IN THE U.S. COPYRIGHT ACT OF A
  4.     "UNITED STATES GOVERNMENT WORK".  IT WAS WRITTEN AS A PART OF THE
  5.     AUTHOR'S OFFICIAL DUTIES AS A GOVERNMENT EMPLOYEE.  THIS MEANS IT
  6.     CANNOT BE COPYRIGHTED.  THIS SOFTWARE IS FREELY AVAILABLE TO THE
  7.     PUBLIC FOR USE WITHOUT A COPYRIGHT NOTICE, AND THERE ARE NO
  8.     RESTRICTIONS ON ITS USE, NOW OR SUBSEQUENTLY.
  9.  
  10. Author:
  11.     K. E. Gorlen
  12.     Bg. 12A, Rm. 2033
  13.     Computer Systems Laboratory
  14.     Division of Computer Research and Technology
  15.     National Institutes of Health
  16.     Bethesda, Maryland 20892
  17.     Phone: (301) 496-1111
  18.     uucp: uunet!nih-csl!kgorlen
  19.     Internet: kgorlen@alw.nih.gov
  20.     September, 1985
  21.  
  22. Function:
  23.     
  24. Functions pertaining to class Class.  Most of these are defined inline
  25. in object.h.
  26.  
  27. Modification History:
  28.  
  29. $Log:    Class.c,v $
  30.  * Revision 3.0  90/05/20  00:19:16  kgorlen
  31.  * Release for 1st edition.
  32.  * 
  33. */
  34.  
  35. #include <stdarg.h>
  36. #include "Object.h"
  37. #include "String.h"
  38. #include "Dictionary.h"
  39. #include "Assoc.h"
  40. #include "OrderedCltn.h"
  41. #include "IdentSet.h"
  42. #include "nihclIO.h"
  43. #include "OIOTbl.h"
  44.  
  45. extern const int NIHCL_RDBADSIG,NIHCL_RDBADTYP,NIHCL_RDWRONGCLASS,NIHCL_RDUNKCLASS,NIHCL_UNKCLASS;
  46.  
  47. #define    THIS    Class
  48. #define    BASE    Object
  49. #define    BASE_CLASSES    BASE::desc()
  50. #define MEMBER_CLASSES
  51. #define VIRTUAL_BASE_CLASSES Object::desc()
  52.  
  53. /* DEFINE_CLASS */
  54.  
  55. Object* Class::reader(OIOin&)
  56. {
  57.     setError(NIHCL_RDUNKCLASS,DEFAULT,"Class");
  58.     return 0;
  59. }
  60. Object* Class::reader(OIOifd&)
  61. {
  62.     setError(NIHCL_RDUNKCLASS,DEFAULT,"Class");
  63.     return 0;
  64. }
  65.  
  66. static Class class_Class("Class",
  67.     ClassList(0,BASE_CLASSES,0), ClassList(0,0), ClassList(0,0),
  68.     1,    // version
  69.     "$Header: /afs/alw.nih.gov/unix/sun4_40c/usr/local/src/nihcl-3.0/share/lib/RCS/Class.c,v 3.0 90/05/20 00:19:16 kgorlen Rel $",
  70.     sizeof(Class), Class::reader, Class::reader, NULL, NULL);
  71.  
  72. const Class* Class::desc()    { return &class_Class; }
  73.  
  74. const Class* Class::isA() const    { return &class_Class; }
  75.  
  76. Object* Class::shallowCopy() const    { return new Class(*this); }
  77.  
  78. _DEFINE_CASTDOWN(Class)
  79.  
  80. // head of the list of all Classes, built by the static constructor of class Class 
  81. static Class* allClasses =0;
  82.  
  83. static Dictionary classDictionary;    // Dictionary of all Classes 
  84. Dictionary& Class::dictionary = classDictionary;
  85.  
  86. unsigned long Class::readFrom_level = 0;    // reset readFromTbl when 0
  87. unsigned long Class::storeOn_level = 0;        // reset storeOnTbl when 0
  88. unsigned long Class::addObjectFlag = 0;        // add object to readFromTbl when 0
  89. IdentSet* Class::storeVBaseTbl = 0;        // table used by storeOn()
  90. ReadFromTbl* Class::readFromTbl    = 0;        // tables used by readFrom()
  91. StoreOnTbl* Class::storeOnTbl = 0;        // tables used by storeOn()
  92.  
  93. #ifdef sparc
  94. // Use magic name to make stdarg work
  95. #define arg0 __builtin_va_alist
  96. #endif
  97.  
  98. ClassList::ClassList(const char* arg0, ...)
  99. {
  100.     va_list ap;
  101.     unsigned nargs = 0;
  102.     va_start(ap, arg0);
  103.     do nargs++; while (va_arg(ap, Class*));
  104.     va_end(ap);
  105.     Class** p = clp = new Class*[nargs];
  106.     va_start(ap, arg0);
  107.     while (nargs--) *p++ = va_arg(ap, Class*);
  108.     va_end(ap);
  109. }
  110.  
  111. Class::Class(const char* name,
  112.     const ClassList& bases, const ClassList& members, const ClassList& vbases,
  113.     unsigned version, const char* ident, unsigned size,
  114.     Object* (*reader)(OIOin&),
  115.     Object* (*binreader)(OIOifd&),
  116.     initorTy initor1, initorTy initor2)
  117. :
  118.     class_name(name),
  119.     class_ident(ident),
  120.     class_bases(bases.clp),
  121.     class_members(members.clp),
  122.     class_vbases(vbases.clp),
  123.     class_version(version),
  124.     inst_size(size),
  125.     inst_reader(reader),
  126.         inst_binreader(binreader),
  127.     class_initor2(initor2)
  128. {
  129.     nextClass = allClasses; allClasses = this;
  130.     class_signature = 0;
  131.     class_number = 0;
  132. //    if (initor1 != 0) initor1(*this);    MASSCOMP cc bug
  133.     initorTy initfun = initor1;
  134.     if (initfun != 0) initfun(*this);
  135. }
  136.  
  137. Class::Class(const Class& c)
  138. :
  139.     class_name(c.class_name),
  140.     class_bases(c.class_bases),
  141.     class_members(c.class_members),
  142.     class_vbases(c.class_vbases),
  143.     class_version(c.class_version),
  144.     class_ident(c.class_ident),
  145.     class_signature(c.class_signature),
  146.     inst_size(c.inst_size),
  147.     inst_reader(c.inst_reader),
  148.         inst_binreader(c.inst_binreader),
  149.     class_initor2(c.class_initor2),
  150.     class_number(c.class_number)
  151. {
  152. }
  153.  
  154. Class::Class(OIOifd&)
  155. :
  156.     class_bases(0),
  157.     class_members(0),
  158.     class_vbases(0),
  159.     class_version(0),
  160.     inst_size(0),
  161.     inst_reader(0),
  162.     inst_binreader(0),
  163.     class_initor2(0)
  164. {
  165. }
  166.  
  167. Class::Class(OIOin&)
  168. :
  169.     class_bases(0),
  170.     class_members(0),
  171.     class_vbases(0),
  172.     class_version(0),
  173.     inst_size(0),
  174.     inst_reader(0),
  175.     inst_binreader(0),
  176.     class_initor2(0)
  177. {
  178. }
  179.  
  180. int Class::compare(const Object& ob) const    // compare Class names 
  181. {
  182.     assertArgSpecies(ob,class_Class,"compare");
  183.     return strcmp(name(),castdown(ob).name());
  184. }
  185.  
  186. unsigned Class::hash() const    { return (const unsigned)this; }
  187.  
  188. bool Class::isEqual(const Object& ob) const    { return this == castdown(&ob); }
  189.  
  190. bool Class::_isKindOf(const Class& clid) const
  191. {
  192.     if (this == &clid) return YES;
  193.     const Class** bp = baseClasses();
  194.     while (*bp) if ((*bp++)->_isKindOf(clid)) return YES;
  195.     return NO;
  196. }
  197.  
  198. void Class::deepenShallowCopy()    { shouldNotImplement("deepenShallowCopy"); }
  199.  
  200. void Class::dumpOn(ostream& strm) const
  201. {
  202.     strm << className() << '[' << name() << '\n';
  203.     strm << "ident: " << ident() << '\n';
  204.     strm << "version: " << version() << '\n';
  205.     strm << "signature: " << signature() << '\n';
  206.     strm << "number: " << number() << '\n';
  207.     strm << "base classes:";
  208.     const Class** p = baseClasses();
  209.     while (*p) strm << ' ' << (*p++)->name();
  210.     strm << '\n';
  211.     strm << "member classes:";
  212.     p = memberClasses();
  213.     while (*p) strm << ' ' << (*p++)->name();
  214.     strm << '\n';
  215.     strm << "virtual base classes:";
  216.     p = virtualBaseClasses();
  217.     while (*p) strm << ' ' << (*p++)->name();
  218.     strm << '\n';
  219.     strm << "]\n";
  220. }
  221.  
  222. void Class::printOn(ostream& strm) const    { strm << class_name; }
  223.  
  224. unsigned Class::size() const    { return inst_size; }
  225.     
  226. void Class::addSignature(unsigned long s)
  227. {
  228. // Assumes that an unsigned long is at least 32 bits
  229.     class_signature = ((class_signature << 3) + (class_signature >> (32-3) & 7) + s) & 0xFFFFFFFF;
  230. }
  231.  
  232. void Class::computeSignature()
  233. {
  234.     if (this == Object::desc()) {
  235.         class_signature = class_version;
  236.         return;
  237.     }
  238.     Class** p = (Class**)class_bases;
  239.     while (*p) addSignature((*p++)->signature());
  240.     if (class_signature == 0) class_signature++;
  241.     p = (Class**)class_members;
  242.     while (*p) addSignature((*p++)->signature());
  243.     if (class_version != 0) addSignature(class_version);
  244.     if (class_signature == 0) class_signature++;
  245. }
  246.  
  247. const Class* Class::lookup(const char* name)
  248. // Find the class descriptor for class "name"
  249. {
  250.     LookupKey* asc = dictionary.assocAt(String(name));
  251.     if (asc == 0) return 0;
  252.     return castdown(asc->value());
  253. }
  254.  
  255. class ReadFromTblMgr {
  256.     friend Object* Class::readFrom(OIOin& strm) const;
  257.     friend Object* Class::readFrom(OIOifd& fd) const;
  258.     ReadFromTblMgr() {
  259.         if (Class::readFrom_level++ == 0) Class::readFromTbl = new ReadFromTbl;
  260.     }
  261.     ~ReadFromTblMgr() {
  262.         if (--Class::readFrom_level == 0) {
  263.             delete Class::readFromTbl;
  264.             Class::readFromTbl = 0;
  265.         }
  266.     }
  267. };
  268.  
  269. Object* Class::readFrom(OIOin& strm) const
  270. {
  271.     ReadFromTblMgr tbl;
  272.     return strm.readObject(*this);
  273. }
  274.  
  275. Object* Class::readObject(OIOin& strm) const
  276. // Called by OIOin::readObject()
  277. {
  278. #ifdef DEBUG_OBJIO
  279.     cerr << "readFrom: read instance of class " << name();
  280. #endif
  281.     addObjectFlag = 0;    // causes Object::Object(OIOin&) to do Class::readFromTbl->add()
  282.     return (*inst_reader)(strm);
  283. }
  284.  
  285. Object::Object(OIOin&)
  286. {
  287.     if (Class::addObjectFlag++ == 0) {
  288.         int objectNum = Class::readFromTbl->add(*this);    // add object to readFromTbl
  289. #ifdef DEBUG_OBJIO
  290.         cerr << ", object #" << objectNum << "\n";
  291. #endif
  292.     }
  293. }
  294.  
  295. Object* Class::readFrom(OIOifd& fd) const
  296. {
  297.     ReadFromTblMgr tbl;
  298.     return fd.readObject(*this);
  299. }
  300.  
  301. Object* Class::readObject(OIOifd& fd) const
  302. // Called by OIOifd::readObject()
  303. {
  304. #ifdef DEBUG_OBJIO
  305.     cerr << "readFrom: read instance of class " << name();
  306. #endif
  307.     addObjectFlag = 0;    // causes Object::Object(OIOifd&) to do Class::readFromTbl->add();
  308.     return (*inst_binreader)(fd);
  309. }
  310.  
  311. Object::Object(OIOifd&)
  312. {
  313.     if (Class::addObjectFlag++ == 0) {
  314.         int objectNum = Class::readFromTbl->add(*this);    // add object to readFromTbl
  315. #ifdef DEBUG_OBJIO
  316.         cerr << ", object #" << objectNum << "\n";
  317. #endif
  318.     }
  319. }
  320.  
  321. void Class::initialize()    // class initialization
  322. {
  323.     register Class*    clp = allClasses;   // add all classes to class dictionary
  324.  
  325. #ifdef DEBUG
  326. while (clp != NULL) { clp->dumpOn(); clp = clp->nextClass; }
  327. clp = allClasses;
  328. #endif
  329.  
  330.     while (clp != NULL) {
  331.         clp->signature();    // compute class signatures
  332.         dictionary.add(*new Assoc(*new String(clp->name()), *clp));
  333.         clp = clp->nextClass;
  334.     }
  335.     clp = allClasses;    // call the initor2 functions
  336.     while (clp != NULL) {
  337.         if (clp->class_initor2 != 0) (*clp->class_initor2)(*clp);
  338.         clp = clp->nextClass;
  339.     }
  340. }
  341.  
  342. bool Class::_storeVBase(void* p)
  343. {
  344.     if (storeVBaseTbl == 0) {
  345.         storeVBaseTbl = new IdentSet(256);
  346.         storeVBaseTbl->add(*(Object*)p);
  347.         return YES;
  348.     }
  349.     if (storeVBaseTbl->includes(*(Object*)p)) return NO;
  350.     storeVBaseTbl->add(*(Object*)p);
  351.     return YES;
  352. }
  353.  
  354. void Class::storer(OIOout&) const { shouldNotImplement("storer"); }
  355.  
  356. void Class::storer(OIOofd&) const { shouldNotImplement("storer"); }
  357.